package com.lagou.edu.annotation.support;

import com.alibaba.druid.util.StringUtils;
import com.lagou.edu.annotation.Autowired;
import com.lagou.edu.annotation.Service;
import com.lagou.edu.factory.BeanDefinition;
import com.lagou.edu.factory.BeanFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DefaultAnnotationHandler {
    private Map<Class<?>, BeanDefinition> hasInstanceBeanCache = new HashMap<>();

    public void processAnnotations(List<String> allClassName) {
        if (allClassName != null) {
            for (String className : allClassName) {
                //根据类名对bean做加载注册到缓存map对象
                processAnnotations(className);
            }
        }
    }

    public void processAnnotations(String className) {
        Class<?> clazz = null;
        try {
            clazz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        if (clazz == null) {
            return;
        }
        //如果反射获取到的类不为空且不是接口且不是注解的话做处理
        if (clazz != null && !clazz.isInterface() && !clazz.isAnnotation()) {
            // AAA.处理对象实例化
            Service service = clazz.getAnnotation(Service.class);
            //如果类上有@Service注解做处理

            if (service != null) {
                // 0.根据当前类名称注入 把beanDefinition（当前类的代理对象和bean实例）注入map
                BeanDefinition beanDefinition = BeanFactory.registryBeanByInterface(clazz.getName(), clazz);
                // 1.service注解有指定id
                String id = service.value();
                if (!StringUtils.isEmpty(id)) {
                    //如果在注解上加上了命名id则根据id注入beanDefinition
                    BeanFactory.registryBean(id, beanDefinition);
                }
                // 2.未指定ID，则根据父接口名注入beanDefinition
                Class<?>[] interfaces = clazz.getInterfaces();
                if (interfaces != null) {
                    for (Class<?> anInterface : interfaces) {
                        BeanFactory.registryBeanByInterface(anInterface.getName(), beanDefinition);
                    }
                }
                //把有实例对象的bean以及beanDefinition放入缓存
                hasInstanceBeanCache.put(clazz, beanDefinition);
            }
        }
    }

    //对带有Autowired注解的属性注入对象实例
    public void doProcessPropertiesBeanAutowired() {
        for (Map.Entry<Class<?>, BeanDefinition> entry : hasInstanceBeanCache.entrySet()) {
            Class<?> aClass = entry.getKey();
            //获取有实例对象bean的所有属性
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                Autowired autowired = field.getAnnotation(Autowired.class);
                //如果属性带有Autowired注解且required=true那么就给属性依赖注入
                if (autowired != null && autowired.required()) {
                    field.setAccessible(true);
                  //根据属性类名获取对象
                    Object   bean = BeanFactory.getBean(field.getType());
                    try {
                        //获取BeanDefinition
                        BeanDefinition needInjected = entry.getValue();
                        //把对象实例赋值给对象
                        field.set(needInjected.getInstance(), bean);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        hasInstanceBeanCache.clear();
    }
}